﻿using Core.Utility.Attributes;
using EnumsNET;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Core.Utility.Helper
{
    /// <summary>
    /// 枚举扩展
    /// </summary>
    public static class EnumHelper
    {
        /// <summary>
        /// 枚举类型转枚举值
        /// </summary>
        /// <typeparam name="TEnum"></typeparam>
        /// <param name="enumValue"></param>
        /// <returns></returns>
        public static TEnum? EnumValueToEnum<TEnum>(long? enumValue) where TEnum : struct, Enum
        {
            List<TEnum> enumList = new List<TEnum>();
            //https://github.com/TylerBrinkley/Enums.NET
            foreach (var temp in Enums.GetMembers<TEnum>())
            {
                if (Convert.ToInt64(temp.Value) == enumValue)
                {
                    return temp.Value;
                }
                else
                {
                    enumList.Add(temp.Value);
                }
            }
            foreach (var enumItem in enumList)
            {
                if (Convert.ToInt64(enumItem) == enumValue)
                {
                    return enumItem;
                }
            }
            return null;
        }

        /// <summary>
        /// 枚举类型转枚举值
        /// </summary>
        /// <typeparam name="TEnum"></typeparam>
        /// <param name="enumString"></param>
        /// <returns></returns>
        public static TEnum? EnumStringToEnum<TEnum>(string? enumString) where TEnum : struct,Enum
        {
            List<TEnum> enumList = new List<TEnum>();
            //https://github.com/TylerBrinkley/Enums.NET
            foreach (var temp in Enums.GetMembers<TEnum>())
            {
                if (temp.Name == enumString)
                {
                    return temp.Value;
                }
                else
                {
                    enumList.Add(temp.Value);
                }
            }
            foreach(var enumItem in enumList)
            {
                if(enumItem.GetName()?.ToLower() == enumString?.ToLower())
                {
                    return enumItem;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取枚举列表
        /// </summary>
        /// <typeparam name="TEnum"></typeparam>
        /// <returns></returns>
        public static List<TEnum> GetEnumList<TEnum>()
            where TEnum : struct, Enum
        {
            List<TEnum> res = new List<TEnum>();
            //https://github.com/TylerBrinkley/Enums.NET
            foreach (var temp in Enums.GetMembers<TEnum>())
            {
                res.Add(temp.Value);
            }
            return res;
        }

        /// <summary>
        /// 获取枚举Attribute列表
        /// </summary>
        /// <typeparam name="TEnum"></typeparam>
        /// <typeparam name="TAttr"></typeparam>
        /// <returns></returns>
        public static Dictionary<TEnum, TAttr> GetEnumAttributeList<TEnum, TAttr>() 
            where TEnum : struct, Enum
            where TAttr : Attribute
        {
            Dictionary<TEnum, TAttr> res = new Dictionary<TEnum, TAttr>();
            //https://github.com/TylerBrinkley/Enums.NET
            foreach (var temp in Enums.GetMembers<TEnum>())
            {
                var attr = temp.Attributes.FirstOrDefault(p => p.GetType() == typeof(TAttr)) as TAttr;
#pragma warning disable CS8604 // 引用类型参数可能为 null。
                res.Add(temp.Value, attr);
#pragma warning restore CS8604 // 引用类型参数可能为 null。
            }
            return res;
        }

        /// <summary>
        /// 获取代码-值-描述特性的枚举信息
        /// </summary>
        /// <param name="isAddAllDataItem">是否添加全部数据项</param>
        /// <returns></returns>
        public static List<EnumCodeValueDescriptionAttributeInfo<TEnum>> GetEnumCodeValueDescriptionInfo<TEnum>(bool isAddAllDataItem = false)
            where TEnum : struct, Enum
        {
            List<EnumCodeValueDescriptionAttributeInfo<TEnum>> res = new List<EnumCodeValueDescriptionAttributeInfo<TEnum>>();
            if(isAddAllDataItem)
            {
                res.Add(EnumCodeValueDescriptionAttributeInfo<TEnum>.AllDataItem);
            }
            int index = 0;
            foreach (var item in Enums.GetMembers<TEnum>())
            {
                index++;
                var info = GetEnumCodeValueDescriptionInfo(item.Value, index);
                res.Add(info);
            }
            return res;
        }

        /// <summary>
        /// 获取代码-值-描述特性的枚举信息
        /// </summary>
        /// <param name="enumSort"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static EnumCodeValueDescriptionAttributeInfo<TEnum> GetEnumCodeValueDescriptionInfo<TEnum>(TEnum param,int enumSort = -1)
            where TEnum : struct, Enum
        {
            EnumCodeValueDescriptionAttributeInfo<TEnum> res = new EnumCodeValueDescriptionAttributeInfo<TEnum>();
            var enumMember = Enums.GetMember(param);
            if (enumMember != null)
            {
                var attr = enumMember.Attributes.FirstOrDefault(p => p.GetType() == typeof(CodeValueDescriptionAttribute)) as CodeValueDescriptionAttribute;
                res = new EnumCodeValueDescriptionAttributeInfo<TEnum>()
                {
                    Description = attr?.Description,
                    Code = attr?.Code,
                    Enum = enumMember.Value,
                    EnumName = enumMember.Name,
                    EnumValue = enumMember.ToInt64(),
                    EnumSort = enumSort,
                    Order = attr?.Order,
                    Value = attr?.Value,
                };
            }
            else
            {
                //未获取到代码值
                res = new EnumCodeValueDescriptionAttributeInfo<TEnum>()
                {
                    Description = null,
                    Code = null,
                    Enum = param,
                    EnumName = param.ToString(),
                    EnumValue = Convert.ToInt64(param),
                    EnumSort = enumSort,
                    Order = null,
                    Value = null,
                };
            }
            return res;
        }
    }
}
